package com.cdie.myschool.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cdie.myschool.common.R;
import com.cdie.myschool.domain.entity.*;
import com.cdie.myschool.domain.vo.DepartmentReportVO;
import com.cdie.myschool.mapper.TeacherTermReportMapper.DepartmentMapper;
import com.cdie.myschool.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 199000201 罗欢
 * @date 2022/10/5 - 9:42
 */
@Service
public class DepartmentReportServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements DepartmentReportService {
    @Autowired
    private TeacherService teacherService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private CourseService courseService;

    @Autowired
    private MajorService majorService;

    @Autowired
    private CalendarService calendarService;




    @Override
    public R departmentDirectory() {
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Department::getDepartmentParentCode,1);
        queryWrapper.between(Department::getDepartmentCode,"01101","01110");
        List<Department> departmentList = list(queryWrapper);
        if (departmentList == null || departmentList.size() == 0) {
            return R.Failed(401,"请求的资源不存在");
        }
        return R.Success(departmentList);
    }

    @Transactional
    @Override
    public R departmentDisplay(String departmentCode) {

        //条件查询（根据选择查询对应的专业信息）
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Department::getDepartmentCode,departmentCode);
        Department department = getOne(queryWrapper);

        DepartmentReportVO departmentReportVO = new DepartmentReportVO();

        //学年、学期  √
        departmentReportVO.setSchoolYear((String) schoolYearAndSemester().get("schoolYear"));
        departmentReportVO.setSemester((String) schoolYearAndSemester().get("semester"));

        //专业总数   √
        int majorCount = majorCount();
        departmentReportVO.setMajorCount(majorCount);

        //在校人数  √
        departmentReportVO.setSchoolEnrollments(schoolEnrollments());

        //新专业数  √
        departmentReportVO.setNewMajor(newMajor(department.getDepartmentCode()));

        //专业覆盖学科门类数  (无相关表数据)

        //专业课程总学分   √
        departmentReportVO.setSumCreditCount(sumCreditCount(departmentCode));

        //课程门数   √
        departmentReportVO.setCourseCount(courseCount(departmentCode));

        //实验课门数   √
        departmentReportVO.setLabsCount(labsCount(departmentCode));

        //本年校外实训基地数量  (无相关表数据)

        //学校创新创业教育课程学时数   √
        departmentReportVO.setInnovateHour(innovateHour());

        //省级以上在线开放课程数   (无相关表数据)

        //专业课门类、公共选修课门类、公共必修课门类百分比  ???
        Map<String,Double> majorList = majorPtc(departmentCode);
        departmentReportVO.setMajorCategories(majorList.get("majorCategories"));
        departmentReportVO.setPublicElective(majorList.get("publicElective"));
        departmentReportVO.setCompulsoryPublic(majorList.get("compulsoryPublic"));

        //专业课门数、公共选修课门数、公共必修课门数百分比  ???
        Map<String,Double> courseList = majorPtc(departmentCode);
        departmentReportVO.setMajorCategoriesCount(courseList.get("majorCategoriesCount"));
        departmentReportVO.setPublicElectiveCount(courseList.get("publicElectiveCount"));
        departmentReportVO.setCompulsoryPublicCount(courseList.get("compulsoryPublicCount"));

        //教师总人数   √
        departmentReportVO.setTeacherCount(teacherCount());

        //师生比  √
        departmentReportVO.setTeacherStudentRatio((double) (teacherCount() / studentCount()));

        //教授、副教授、讲师、助教百分比  √
        Map<String,Double> titleList = titlePtc(departmentCode);
        departmentReportVO.setProfessor(titleList.get("professorCount"));
        departmentReportVO.setAssociateProfessor(titleList.get("associateProfessorCount"));
        departmentReportVO.setLecturer(titleList.get("lecturerCount"));
        departmentReportVO.setAssistant(titleList.get("assistantCount"));

        //博士、硕士、学士、无学位百分比  √
        Map<String, Double> degreeList = degreePtc(departmentCode);
        departmentReportVO.setDr(degreeList.get("drCount"));
        departmentReportVO.setMem(degreeList.get("memCount"));
        departmentReportVO.setBachelor(degreeList.get("bachelorCount"));
        departmentReportVO.setNoAward(degreeList.get("noAwardCount"));

        //年龄分布百分比   √(不能根据身份证号判断年龄)
        Map<String, Integer> ageList = agePtc(departmentCode);
        departmentReportVO.setAgeOne(ageList.get("ageOneCount"));
        departmentReportVO.setAgeTwo(ageList.get("ageTwoCount"));
        departmentReportVO.setAgeThree(ageList.get("ageThreeCount"));
        departmentReportVO.setAgeFour(ageList.get("ageFourCount"));


        return R.Success(departmentReportVO);
    }

    /**
     * 获取专业总数
     * @return
     */
    public int majorCount(){
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.between(Department::getDepartmentCode,Integer.parseInt("01101"),Integer.parseInt("01110"));
        int majorCount = count(queryWrapper);
        return majorCount;
    }

    /**
     * 在校人数统计
     * @return
     */
    public int schoolEnrollments(){
        int schoolEnrollments = teacherCount() + studentCount();
        return schoolEnrollments;
    }

    /**
     * 各学院课程总学分
     * @return
     */
    public BigDecimal sumCreditCount(String departmentCode) {
        QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
        int department = Integer.parseInt(departmentCode);
        queryWrapper.select("sum(course_credit) as sumAll").eq("department_code", department);

        Map<String, Object> map = courseService.getMap(queryWrapper);

        if(map == null || map.isEmpty()){
            BigDecimal sumCount = BigDecimal.valueOf(0.0);
            return sumCount;
        }
        BigDecimal sumCount = (BigDecimal) map.get("sumAll");
        return sumCount;
    }

    /**
     * 对应课程门数
     * @param departmentCode
     * @return
     */
    public int courseCount(String departmentCode){
        QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
        int department = Integer.parseInt(departmentCode);
        queryWrapper.select("DISTINCT course_name").eq("course_status",1).eq("department_code",department);
        int courseCount = courseService.count(queryWrapper);
        return courseCount;
    }

    /**
     * 实验课门数
     * @param departmentCode
     * @return
     */
    public int labsCount(String departmentCode){
        LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
        int department = Integer.parseInt(departmentCode);
        queryWrapper.eq(Course::getCourseStatus,1)
                .eq(StringUtils.isNotEmpty(departmentCode),Course::getDepartmentCode,department);
        queryWrapper.like(Course::getCourseName,"%实验%");
        int labsCount = courseService.count(queryWrapper);
        return labsCount;
     }

    /**
     * 创新创业学时
     * @return
     */
    public Double innovateHour(){
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Department::getDepartmentName,"%创新创业%");
        List<Department> departmentList = list(queryWrapper);
        Double innovateHour = 0.0;
        for (Department department : departmentList){
            LambdaQueryWrapper<Course> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(StringUtils.isNotEmpty(department.getDepartmentCode()), Course::getDepartmentCode,department.getDepartmentCode());
            List<Course> courseList = courseService.list(lambdaQueryWrapper);
            for (Course course : courseList){
                innovateHour += course.getCourseHours();

            }
        }
        return innovateHour;
    }

    public Map<String,Double> majorPtc(String departmentCode){//course_category
        LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
        int department = Integer.parseInt(departmentCode);
        queryWrapper.eq(Course::getCourseStatus,1).eq(Course::getDepartmentCode,department);
        List<Course> courseList = courseService.list(queryWrapper);

        int majorCategories = 0;
        int publicElective = 0;
        int compulsoryPublic = 0;

        int majorCategoriesCount = 0;
        int publicElectiveCount = 0;
        int compulsoryPublicCount = 0;

        for (Course course : courseList){
            if (course.getCourseCategory() == 0){
                majorCategories+=1;
                majorCategoriesCount+=1;
            }else if(course.getCourseCategory() == 1){
                publicElective+=1;
                publicElectiveCount+=1;
            }else {
                compulsoryPublic+=1;
                compulsoryPublicCount+=1;
            }
        }


        //计算职称百分比
        Map<String,Double> majorMap = new HashMap<>();
        majorMap.put("majorCategories", (double) majorCategories);
        majorMap.put("publicElective", (double) publicElective);
        majorMap.put("compulsoryPublic", (double) compulsoryPublic);

        majorMap.put("majorCategoriesCount", (double) majorCategoriesCount);
        majorMap.put("publicElectiveCount", (double) publicElectiveCount);
        majorMap.put("compulsoryPublicCount", (double) compulsoryPublicCount);
        return majorMap;


    }


    /**
     * 教师总人数
     * @return
     */
    public int teacherCount(){
        QueryWrapper<Teacher> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT teacher_code").eq("teacher_current_status","on"); //根据教师工号进行去重
        int teacherCount = teacherService.count(queryWrapper);
        return teacherCount;
    }

    /**
     * 学生总人数
     * @return
     */
    public int studentCount(){
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT student_code").eq("student_in",1); //根据学生学号进行去重
        int studentCount = studentService.count(queryWrapper);
        return studentCount;
    }

    /**
     * 教师年龄百分比
     * @return
     */
    public Map<String,Integer> agePtc(String departmentCode){
        LambdaQueryWrapper<Teacher> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teacher::getTeacherCurrentStatus,"on");
        queryWrapper.eq(Teacher::getDepartmentCode,departmentCode);
        List<Teacher> teacherList = teacherService.list(queryWrapper);

        int ageOneCount = 0;
        int ageTwoCount = 0;
        int ageThreeCount = 0;
        int ageFourCount = 0;

        for(Teacher teacher : teacherList){
            int age = teacher.getTeacherAge();
            if (age <= 35 && age >= 0){
                ageOneCount+=1;
            }else if (age >= 36 && age <= 45){
                ageTwoCount+=1;
            }else if (age >= 46 && age <= 55){
                ageThreeCount+=1;
            }else {
                ageFourCount+=1;
            }
        }
        //计算年龄百分比
        Map<String,Integer> ageMap = new HashMap<>();
        ageMap.put("ageOneCount", ageOneCount);
        ageMap.put("ageTwoCount", ageTwoCount);
        ageMap.put("ageThreeCount",ageThreeCount);
        ageMap.put("ageFourCount", ageFourCount);

        return ageMap;
    }

    /**
     * 专业覆盖门类数
     * @param departmentCode
     * @return
     */
    public int coverCourse(String departmentCode){
        QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT course_name") //对课程名进行去重
                .eq("department_code",departmentCode) //院系所号
                .eq("course_status",1); //是否可用

        int coverCourse = courseService.count(queryWrapper);
        return coverCourse;
    }

    /**
     * 新专业数
     * @param departmentCode
     * @return
     */
    public int newMajor(String departmentCode){
        QueryWrapper<Major> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT major_name")
                .eq("department_code" ,departmentCode)
                .eq("major_status",1)
                .eq("new_status",1);

        int newMajor = majorService.count(queryWrapper);
        return newMajor;
    }

    /**
     * 博士、硕士、学士、无学位百分比
     * @return
     */
    public Map<String,Double> degreePtc(String departmentCode){
        LambdaQueryWrapper<Teacher> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teacher::getTeacherCurrentStatus,"on");
        queryWrapper.eq(Teacher::getDepartmentCode,departmentCode);
        List<Teacher> teacherList = teacherService.list(queryWrapper);

        int drCount = 0;
        int memCount = 0;
        int bachelorCount = 0;
        int noAwardCount = 0;

        for (Teacher teacher : teacherList){
            if (teacher.getTeacherDegree() == 0){
                drCount+=1;
            }else if(teacher.getTeacherDegree() == 1){
                memCount+=1;
            }else if (teacher.getTeacherDegree() == 2){
                bachelorCount+=1;
            }else {
                noAwardCount+=1;
            }
        }
        //计算职称百分比
        Map<String,Double> degreeMap = new HashMap<>();
        degreeMap.put("drCount", (double) drCount);
        degreeMap.put("memCount", (double) memCount);
        degreeMap.put("bachelorCount", (double) bachelorCount);
        degreeMap.put("noAwardCount", (double) noAwardCount);
        return degreeMap;
    }

    /**
     * 教授、副教授、讲师、助教百分比
     * @return
     */
    public Map<String,Double> titlePtc(String departmentCode){
        LambdaQueryWrapper<Teacher> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teacher::getTeacherCurrentStatus,"on");
        queryWrapper.eq(Teacher::getDepartmentCode,departmentCode);
        List<Teacher> teacherList = teacherService.list(queryWrapper);

        int professorCount = 0;
        int associateProfessorCount = 0;
        int lecturerCount = 0;
        int assistantCount = 0;

        for (Teacher teacher : teacherList){
            if (teacher.getTeacherJobTitle() == 0){
                professorCount+=1;
            }else if(teacher.getTeacherJobTitle() == 1){
                associateProfessorCount+=1;
            }else if (teacher.getTeacherJobTitle() == 2){
                lecturerCount+=1;
            }else {
                assistantCount+=1;
            }
        }
        //计算职称百分比
        Map<String,Double> titleMap = new HashMap<>();
        titleMap.put("professorCount", (double) professorCount);
        titleMap.put("associateProfessorCount", (double) associateProfessorCount);
        titleMap.put("lecturerCount", (double) lecturerCount);
        titleMap.put("assistantCount", (double) assistantCount);
        return titleMap;
    }

    /**
     * 获取学年学期
     * @return
     */
    public Map<String,Object> schoolYearAndSemester(){
        //设置时间格式
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Map<String,Object> map = new HashMap<>();
        //获取当前时间
        Date date = new Date();
        String year = "";
        try {
            date = format.parse(format.format(date));
            year = format.format(date).substring(0).substring(0,4);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        map.put("schoolYear",year);

        //查询学年
        LambdaQueryWrapper<Calendar> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Calendar::getSchoolYear,year);
        List<Calendar> calendarList = calendarService.list(lambdaQueryWrapper);

        //查询学期
        for (Calendar calendar : calendarList){
            Date beginTime = calendar.getBeginTime();
            Date endTime = calendar.getEndTime();
            int beginStatus = date.compareTo(beginTime);
            int endStatus = date.compareTo(endTime);
            if (beginStatus > 0 && endStatus < 0){
                map.put("semester",calendar.getSemester());
            }
        }
        return map;
    }



}
